//
//  CACache.m
//  Cache
//
//  Created by caixiang on 2021/8/14.
//

#import "ACNSCache.h"
#import <UIKit/UIKit.h>
#import <pthread.h>

@interface ACNSCache (){
    pthread_mutex_t _weakCacheLock;
    NSMapTable *_weakCache;// strong-weak cache
}

@end

@implementation ACNSCache

- (instancetype)init {
    self = [super init];
    if (self) {
        pthread_mutex_init(&_weakCacheLock, NULL);
        [self commonInit];
    }
    return self;
}

- (void)commonInit {
    _weakCache = [[NSMapTable alloc] initWithKeyOptions:NSPointerFunctionsStrongMemory valueOptions:NSPointerFunctionsWeakMemory capacity:0];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_appDidReceiveMemoryWarningNotification) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_appDidEnterBackgroundNotification) name:UIApplicationDidEnterBackgroundNotification object:nil];
}

- (void)setObject:(id)object forKey:(id)key {
    [self setObject:object forKey:key cost:0];
}

- (void)setObject:(id)obj forKey:(id)key cost:(NSUInteger)g {
    [super setObject:obj forKey:key cost:g];
    if (key && obj) {
        pthread_mutex_lock(&_weakCacheLock);
        [_weakCache setObject:obj forKey:key];
        pthread_mutex_unlock(&_weakCacheLock);
    }
}

- (id)objectForKey:(id)key {
    id obj = [super objectForKey:key];
    if (key && !obj) {
        pthread_mutex_lock(&_weakCacheLock);
        obj = [_weakCache objectForKey:key];
        pthread_mutex_unlock(&_weakCacheLock);
        if (obj) {
            [super setObject:obj forKey:key cost:0];
        }
    }
    return obj;
}

- (void)removeObjectForKey:(id)key {
    [super removeObjectForKey:key];
    if (key) {
        pthread_mutex_lock(&_weakCacheLock);
        [_weakCache removeObjectForKey:key];
        pthread_mutex_unlock(&_weakCacheLock);
    }
}

- (void)removeAllObjects {
    [super removeAllObjects];
    pthread_mutex_lock(&_weakCacheLock);
    [_weakCache removeAllObjects];
    pthread_mutex_unlock(&_weakCacheLock);
}

- (void)_appDidReceiveMemoryWarningNotification {
    if (self.didReceiveMemoryWarningBlock) {
        self.didReceiveMemoryWarningBlock(self);
    }
    [super removeAllObjects];
}

- (void)_appDidEnterBackgroundNotification {
    if (self.didEnterBackgroundBlock) {
        self.didEnterBackgroundBlock(self);
    }
    [super removeAllObjects];
}

@end
